package com.googlecode.cswish.struts;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.Validator;
import com.opensymphony.xwork2.validator.ValidatorConfig;
import com.opensymphony.xwork2.validator.ValidatorFactory;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

/**
 * Validate array / collection object
 * 
 * @author jerry.feng Date: 2008-11-14
 */
public class CollectionValidator extends FieldValidatorSupport {

	@Inject
	private ValidatorFactory validatorFactory;
	
	private String prefix;
	
	private ValueStack stack;
	
	private Map<String, String> extParam = new HashMap<String, String>();
	
	public Map<String, String> getExtParam() {
		return extParam;
	}

	public void setExtParam(Map<String, String> extParam) {
		this.extParam = extParam;
	}
	
	public String getValidatorType() {
		String type = extParam.get("validatorType");
		return type;
	}
	
	@Override
	public void setValueStack(ValueStack stack) {
		this.stack = stack;
		super.setValueStack(stack);
	}
	
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public String getPrefix() {
		return this.prefix;
	}
	
	/////////////////// Compatibility For form-close-validate.ftl /////////////
	// stringlength
	public boolean getTrim() {
		return Boolean.valueOf(extParam.get("trim"));
	}
	
	public int getMaxLength() {
		String len = extParam.get("maxLength");
		if (len != null) {
			return Integer.parseInt(len);
		} else {
			return 0;
		}
	}
	
	public int getMinLength() {
		String len = extParam.get("minLength");
		if (len != null) {
			return Integer.parseInt(len);
		} else {
			return 0;
		}
	}
	
	// regex
	public String getExpression() {
		return extParam.get("expression");
	}
	
	// int
	public Integer getMax() {
		String len = extParam.get("max");
		if (len != null) {
			return Integer.parseInt(len);
		} else {
			return 0;
		}
	}
	
	// double
	public String getMaxInclusive() {
		return extParam.get("maxInclusive");
	}
	
	public String getMaxExclusive() {
		return extParam.get("maxExclusive");
	}
	///////////////////////////////////////////////////////////////////////////
	
	@Override
	public void validate(Object object) throws ValidationException {
		Validator validator = initValidator();
		
        Object value = this.getFieldValue(getPrefix(), object);
		if (value == null) {
			return;
		}
        
        if (value instanceof Collection) {
        	Collection<?> coll = (Collection<?>)value;
        	if (coll != null) {
        		for (Object obj : coll) {
        			validator.validate(obj);
        		}
        	}
        } else if (value.getClass().isArray()) {
        	Object[] arrays = (Object[])value;
        	for (Object obj : arrays) {
        		validator.validate(obj);
        	}
        }
	}
	
	protected Validator initValidator() {
		ValidatorConfig.Builder builder = new ValidatorConfig.Builder(getValidatorType());
		builder.defaultMessage(getDefaultMessage());
		builder.addParams(extParam);
		
		ValidatorConfig cfg = builder.build();
		Validator validator = validatorFactory.getValidator(cfg);
		validator.setValueStack(stack);
		validator.setValidatorType(getValidatorType());
		validator.setValidatorContext(getValidatorContext());
		return validator;
	}
}
